package view.main;

import info.clearthought.layout.TableLayout;

import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import model.game.GameController;
import model.game.InformationLayer;

public class MainView extends JFrame {

  private static final long serialVersionUID = 1L;

  private static final long kDelayInMs = 250L;

  private GameController controller_;
  private InformationLayer info_;

  private Timer night_timer_;

  private boolean night_;

  enum InfoState {
    kShop,
    kSprite,
    kTeleport,
    kInventory
  }

  private InfoState last_state_;

  private InfoState state_;

  private JPanel screen_;

  private DefaultListModel log_model_;
  private JList log_;

  private DefaultListModel shop_model_;
  private JList shop_;

  private JButton pickshop_;
  private JButton picksprite_;
  private JButton pickteleport_;
  private JButton pickinventory_;

  private JButton buy_;
  private JButton sell_;
  private JButton extra_;

  private JLabel season_;
  private JPanel disaster_;
  private JLabel time_;

  private JLabel item_;
  private JLabel tool_;
  private JButton plant_;
  private JButton use_;
  private JButton discard_;
  private JButton sell_item_;
  private JButton sleep_;

  private JButton next_item_;
  private JButton prev_item_;
  private JButton next_tool_;
  private JButton prev_tool_;

  private JButton move_up_;
  private JButton move_down_;
  private JButton move_left_;
  private JButton move_right_;

  private JButton save_;
  private JButton skip_night_;

  private JScrollPane display_screen_;

  private JPanel outermost_layer_;
  private JLabel helper_;

  private JLabel shop_header_;
  private JLabel shop_helper_;

  private Information information_;
  private boolean lost_;

  public MainView(GameController controller, InformationLayer info) {

    this.setTitle("Gagal Panen 2");

    lost_ = false;
    information_ = new Information();

    helper_ = new JLabel();
    helper_.setVisible(false);
    helper_.setBounds(0, 0, 225, 450);

    controller_ = controller;
    info_ = info;

    night_ = false;

    JPanel cp = new JPanel();
    outermost_layer_ = cp;
    cp.setBounds(0, 0, 1024, 800);
    this.getContentPane().add(cp);

    // sets the layout using table layout
    double[][] table_size = {
                                         // should be fill
        {400.0, 272.0, 64.0, 64.0, 64.0, 200.0, 64.0, 64.0, 64.0},

        {64.0, 64.0, 64.0, 64.0, 64.0, 64.0, 64.0, TableLayout.FILL, 64.0, 64.0, 64.0}
    };

    // table layout if x, y

    cp.setLayout(new TableLayout(table_size));

    // main display screen
    screen_ = new JPanel();
    screen_.setLayout(null);
    screen_.removeAll();
    display_screen_ = new JScrollPane(screen_);
    cp.add(display_screen_, "0, 0, 5, 7");

    log_model_ = new DefaultListModel();
    log_ = new JList(log_model_);

    log_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          updateAll();
        }
      }
    );

    cp.add(new JScrollPane(log_), "0, 8, 0, 10");

    shop_model_ = new DefaultListModel();
    JList list = new JList(shop_model_);
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    shop_ = list;

    shop_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          updateAll();
        }
      }
    );

    cp.add(new JScrollPane(shop_), "1, 8, 1, 10");

    pickshop_ = new JButton();
    pickshop_.setText("Shop");
    pickshop_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!pickshop_.isEnabled()) return;
          state_ = InfoState.kShop;
          buy_.setEnabled(true);
          buy_.setText("Buy");
          buy_.updateUI();
          sell_.setEnabled(true);
          sell_.setText("Sell");
          sell_.updateUI();
          extra_.setEnabled(false);
          extra_.setText("");
          extra_.updateUI();

          updateAll();
        }
      }
    );
    cp.add(pickshop_, "2, 8, 2, 8");

    picksprite_ = new JButton();
    picksprite_.setText("Sprite");
    picksprite_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!picksprite_.isEnabled()) return;
          state_ = InfoState.kSprite;
          buy_.setEnabled(true);
          buy_.setText("Hire");
          buy_.updateUI();
          sell_.setEnabled(true);
          sell_.setText("Fire");
          sell_.updateUI();
          extra_.setEnabled(true);
          extra_.setText("Upgrade");
          extra_.updateUI();

          updateAll();
        }
      }
    );
    cp.add(picksprite_, "2, 9, 2, 9");

    pickteleport_ = new JButton();
    pickteleport_.setText("Teleport");
    pickteleport_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!pickteleport_.isEnabled()) return;
          state_ = InfoState.kTeleport;
          buy_.setEnabled(true);
          buy_.setText("Teleport");
          buy_.updateUI();
          sell_.setEnabled(false);
          sell_.setText("");
          sell_.updateUI();
          extra_.setEnabled(false);
          extra_.setText("");
          extra_.updateUI();

          updateAll();
        }
      }
    );
    cp.add(pickteleport_, "2, 10, 2, 10");

    pickinventory_ = new JButton();
    pickinventory_.setText("Inventory");
    pickinventory_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!pickinventory_.isEnabled()) return;
          state_ = InfoState.kInventory;
          buy_.setEnabled(false);
          buy_.setText("");
          buy_.updateUI();
          sell_.setEnabled(false);
          sell_.setText("");
          sell_.updateUI();
          extra_.setEnabled(false);
          extra_.setText("");
          extra_.updateUI();
          updateAll();
        }
      }
    );
    cp.add(pickinventory_, "3, 8, 3, 8");

    buy_ = new JButton();
    buy_.setText("Buy");
    buy_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!buy_.isEnabled()) return;
          if (state_ == InfoState.kShop) {
            int selected = shop_.getSelectedIndex();
            if (selected != -1) {
              controller_.playerBuy((String)shop_.getSelectedValue(), 1);
              updateAll();
            }
          } else if (state_ == InfoState.kSprite) {
            int selected = shop_.getSelectedIndex();
            if (selected != -1) {
              controller_.playerHireSprite((String)shop_.getSelectedValue());
              updateAll();
            }
          } else if (state_ == InfoState.kTeleport) {
            int selected = shop_.getSelectedIndex();
            if (selected != -1) {
              controller_.playerTeleport((String)shop_.getSelectedValue());
              updateAll();
            }
          }

          updateAll();
        }
      }
    );
    cp.add(buy_, "4, 8");

    sell_ = new JButton();
    sell_.setText("Sell");
    sell_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!sell_.isEnabled()) return;
          if (state_ == InfoState.kShop) {
            controller_.playerSell(1);
          } else if (state_ == InfoState.kSprite) {
            if (shop_.getSelectedIndex() != -1) {
              controller_.playerFireSprite((String)shop_.getSelectedValue());
            }
          }
          updateAll();
        }
      }
    );
    cp.add(sell_, "4, 9");

    extra_ = new JButton();
    extra_.setText("");
    extra_.setEnabled(false);
    extra_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!extra_.isEnabled()) return;
          if (state_ == InfoState.kSprite) {
            // upgrade
            if (shop_.getSelectedIndex() != -1) {
              JFrame frame = MainView.this;
                int answer = JOptionPane.showConfirmDialog(frame,
                        "Do you want to upgrade " +
                        shop_.getSelectedValue() +
                        " by paying " +
                        info_.getUpgradeCostOfASprite((String)
                        shop_.getSelectedValue()) +
                        "?",
                        "Upgrade",
                        JOptionPane.YES_NO_OPTION);
                if (answer == JOptionPane.YES_OPTION) {
                  controller_.upgradeSprite((String)shop_.getSelectedValue());
                  updateAll();
                }
            } else {
              log_model_.add(0, "<html><font color='red'>No sprite selected</font></html");
            }
          }
        }
      }
    );
    cp.add(extra_, "4, 10");
    
    // initial state
    state_ = InfoState.kShop;

    disaster_ = new JPanel();
    disaster_.setLayout(null);
    cp.add(new JScrollPane(disaster_), "6, 0, 7, 0");

    season_ = new JLabel();
    cp.add(season_, "8, 0");

    time_ = new JLabel();
    cp.add(time_, "6, 1, 8, 1");

    shop_header_ = new JLabel();
    JScrollPane sp2 = new JScrollPane(shop_header_);
    sp2.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
    sp2.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    cp.add(sp2, "5, 8");

    shop_helper_ = new JLabel();
    shop_helper_.setSize(200, 1);

    JScrollPane sp = new JScrollPane(shop_helper_);
    sp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    cp.add(sp, "5, 9, 5, 10");

    item_ = new JLabel();
    cp.add(item_, "7, 2");

    tool_ = new JLabel();
    cp.add(tool_, "7, 4");

    plant_ = new JButton();
    plant_.setText("Plant");
    plant_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!plant_.isEnabled()) return;
          controller_.playerPlant();
          updateAll();
        }
      }
    );
    cp.add(plant_, "7, 3");

    discard_ = new JButton();
    discard_.setText("Discard");
    discard_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!discard_.isEnabled()) return;
          controller_.playerDiscard(1);
          updateAll();
        }
      }
    );
    cp.add(discard_, "8, 3");

    sell_item_ = new JButton();
    sell_item_.setText("Sell");
    sell_item_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!sell_item_.isEnabled()) return;
          controller_.playerSell(1);
          updateAll();
        }
      }
    );
    cp.add(sell_item_, "6, 3");

    use_ = new JButton();
    use_.setText("Use");
    use_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!use_.isEnabled()) return;
          controller_.playerPerformToolAction();
          updateAll();
        }
      }
    );
    cp.add(use_, "7, 5");

    next_item_ = new JButton();
    next_item_.setText("Next");
    next_item_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!next_item_.isEnabled()) return;
          controller_.showNextInventory();
          updateAll();
        }
      }
    );
    cp.add(next_item_, "8, 2");

    prev_item_ = new JButton();
    prev_item_.setText("Prev");
    prev_item_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!prev_item_.isEnabled()) return;
          controller_.showPreviousInventory();
          updateAll();
        }
      }
    );
    cp.add(prev_item_, "6, 2");

    next_tool_ = new JButton();
    next_tool_.setText("Next");
    next_tool_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!next_tool_.isEnabled()) return;
          controller_.showNextTool();
          updateAll();
        }
      }
    );
    cp.add(next_tool_, "8, 4");

    prev_tool_ = new JButton();
    prev_tool_.setText("Prev");
    prev_tool_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!prev_tool_.isEnabled()) return;
          controller_.showPreviousTool();
          updateAll();
        }
      }
    );
    cp.add(prev_tool_, "6, 4");

    sleep_ = new JButton();
    sleep_.setText("Sleep");
    sleep_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!sleep_.isEnabled()) return;
          controller_.playerSleep();
          updateAll();
        }
      }
    );
    cp.add(sleep_, "8, 6");

    move_up_ = new JButton();
    move_up_.setText("Up");
    move_up_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!move_up_.isEnabled()) return;
          controller_.playerMoveUp();
          updateAll();
        }
      }
    );
    cp.add(move_up_, "7, 8");

    move_down_ = new JButton();
    move_down_.setText("Down");
    move_down_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!move_down_.isEnabled()) return;
          controller_.playerMoveDown();
          updateAll();
        }
      }
    );
    cp.add(move_down_, "7, 10");

    move_left_ = new JButton();
    move_left_.setText("Left");
    move_left_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!move_left_.isEnabled()) return;
          controller_.playerMoveLeft();
          updateAll();
        }
      }
    );
    cp.add(move_left_, "6, 9");

    move_right_ = new JButton();
    move_right_.setText("Right");
    move_right_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!move_right_.isEnabled()) return;
          controller_.playerMoveRight();
          updateAll();
        }
      }
    );
    cp.add(move_right_, "8, 9");

    save_ = new JButton();
    save_.setText("Save");
    save_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!save_.isEnabled()) return;
          controller_.playerSave();
          updateAll();
        }
      }
    );
    cp.add(save_, "6, 6");

    skip_night_ = new JButton();
    skip_night_.setText("<html>Skip<br/>Night</html>");
    skip_night_.setEnabled(false);
    skip_night_.addMouseListener(
      new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
          if (!skip_night_.isEnabled()) return;
          if (!night_) return;
          night_ = false;
          night_timer_.cancel();
          night_timer_.purge();
          controller_.skipNight();
          setEnabledAllButtons(true);
          updateAll();
        }
      }
    );
    cp.add(skip_night_, "7, 6");

    night_timer_ = new Timer();

    initGraphic();

    this.pack();

    updateAll();

    this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    this.setVisible(true);
  }

  private void setEnabledAllButtons(boolean status) {
    pickshop_.setEnabled(status);
    picksprite_.setEnabled(status);
    pickteleport_.setEnabled(status);
    pickinventory_.setEnabled(status);

    if (status == false) {
      buy_.setEnabled(status);
      sell_.setEnabled(status);
      extra_.setEnabled(status);
    } else {
      if (state_ == InfoState.kShop) {
        buy_.setEnabled(true);
        sell_.setEnabled(true);
        extra_.setEnabled(false);
      } else if (state_ == InfoState.kSprite) {
        buy_.setEnabled(true);
        sell_.setEnabled(true);
        extra_.setEnabled(true);
      } else if (state_ == InfoState.kTeleport) {
        buy_.setEnabled(true);
        sell_.setEnabled(false);
        extra_.setEnabled(false);
      } else if (state_ == InfoState.kInventory) {
        buy_.setEnabled(false);
        sell_.setEnabled(false);
        extra_.setEnabled(false);
      }
    }

  plant_.setEnabled(status);
  use_.setEnabled(status);
  discard_.setEnabled(status);
  sleep_.setEnabled(status);
  sell_item_.setEnabled(status);

  next_item_.setEnabled(status);
  prev_item_.setEnabled(status);
  next_tool_.setEnabled(status);
  prev_tool_.setEnabled(status);

  move_up_.setEnabled(status);
  move_down_.setEnabled(status);
  move_left_.setEnabled(status);
  move_right_.setEnabled(status);

  save_.setEnabled(status);

  skip_night_.setEnabled(!status);
  }

  /**
   * Indirection class for ArrayList<Image>
   */
  class ArrayListImage {
    public ArrayList<Image> rep_;
    public ArrayListImage() {
      rep_ = new ArrayList<Image>();
    }
  }

  /**
   * Indirection class for ArrayList<JLabel>
   */
  class ArrayListJLabel {
    public ArrayList<JLabel> rep_;
    public ArrayListJLabel() {
      rep_ = new ArrayList<JLabel>();
    }
  }

  private String lastmap_;
  private ArrayListImage lastimages_[][];
  private ArrayListJLabel components_[][];
  private Image lastbg_;

  private JLabel lastbg_label_;

  int last_r, last_c;

  private void initGraphic() {
    last_r = last_c = 0;
    lastbg_label_ = null;
    lastmap_ = null;
    lastimages_ = null;
    lastbg_ = null;
    components_ = null;
    last_state_ = null;
  }

  private void updateMainGraphic() {

    int row, col;
    row = info_.getCurrentMapRowsCount();
    col = info_.getCurrentMapColumnsCount();

    if (last_r != row || last_c != col) {
      // clean screen
      screen_.removeAll();
      initGraphic();

      screen_.setPreferredSize(new Dimension(col * 64, row * 64));
      last_r = row;
      last_c = col;
      lastimages_ = new ArrayListImage[last_r][last_c];
      components_ = new ArrayListJLabel[last_r][last_c];

      for (int r = 0; r < last_r; ++r) {
        for (int c = 0; c < last_c; ++c) {
          lastimages_[r][c] = new ArrayListImage();
          components_[r][c] = new ArrayListJLabel();
        }
      }
    }
    
    for (int y = 0; y < row; ++y) {
      for (int x = 0; x < col; ++x) {
        ArrayList<Image> imgs = info_.getAllImagesAtCoordinate(x, y);
        if (lastimages_[y][x].rep_.equals(imgs)) continue;
        for (JLabel label : components_[y][x].rep_) {
          screen_.remove(label);
        }
        lastimages_[y][x].rep_ = imgs;
        components_[y][x].rep_.clear();
        for (int i = imgs.size()-1; i >= 0; --i) {
          Image img = imgs.get(i);
          JLabel ilabel = new JLabel(new ImageIcon(img));
          ilabel.setBounds(x * 64, y * 64, 64, 64);
          screen_.add(ilabel);
          components_[y][x].rep_.add(0, ilabel);

          if (i == 0) {
            ilabel.addMouseListener(new CellListener(
                    info_, information_, controller_, this, x, y));
          }
        }
      }
    }

    Image buffer = info_.getCurrentMapImage();
    if (lastbg_ != null && !lastbg_.equals(buffer)) {
      if (lastbg_label_ != null) screen_.remove(lastbg_label_);
      lastbg_label_ = new JLabel(new ImageIcon(buffer));
      lastbg_label_.setBounds(0, 0, col * 64, row * 64);
      screen_.add(lastbg_label_);
    }

    screen_.updateUI();
  }

  private void handleException(Exception ex) {
    // TODO
  }

  /**
   * Timer action during each night's tick
   */
  class NightTask extends TimerTask {

    /**
    * Constructs the object, sets the string to be output in function run()
    * @param str
    */
    NightTask() {
    }

    /**
    * When the timer executes, this code is run.
    */
    synchronized public void run() {

      if (!night_) {
        night_timer_.cancel();
        night_timer_.purge();
        return;
      }

      controller_.tickNight();
      if (!info_.isNight()) {
        // night has ended
        night_timer_.cancel();
        night_timer_.purge();
        setEnabledAllButtons(true);
        night_ = false;
        updateAll();
        return;
      }
      updateLogAndError();
      updateMainGraphic();
      time_.setText("<html>Time: " +
              info_.getNightTime() + "/" + info_.getNightLength() +
              "<br/>" + 
              "Day: " + info_.getCurrentDay() +
          "<br/>NIGHT</html>");
      //time_.updateUI();
    }
  }

  /**
   * Updates log and error
   */
  private void updateLogAndError() {

    String msg = info_.getMessage();
    String err = info_.getError();

    while (msg.equals("") == false) {

      if (msg.equals("You win the game")) {
        if (lost_) return;
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            WinGame app = new WinGame();
          }
        });
        this.dispose();
        return;
      }

      if (msg.equals("You lose the game")) {
        if (lost_) return;
        lost_ = true;
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            LoseGame app = new LoseGame();
          }
        });
        this.dispose();

        return;
      }

      log_model_.add(0, msg);
      //log_.updateUI();
      msg = info_.getMessage();
    }

    while (err.equals("") == false) {
      log_model_.add(0, "<html><font color='red'>" + err + "</font></html>");
      //log_.updateUI();
      err = info_.getError();
    }

    msg = info_.getImportantMessage();

    while (msg.equals("") == false) {
      log_model_.add(0, "<html><font color='blue'>" + msg + "</font></html>");
      //log_.updateUI();
      msg = info_.getImportantMessage();
    }
  }

  /**
   * Update all things after each action
   */
  void updateAll() {
    if (night_) return;
    
    // update main layar
    updateMainGraphic();

    // update labels
    updateLogAndError();

    // update shop/etc. list
    if (last_state_ != state_) {
      last_state_ = state_;
      shop_model_.removeAllElements();
      if (state_ == InfoState.kShop) {
        // shop shop in model
        ArrayList<String> names = info_.getAllShopItemsNames();
        for (String name : names) {
          shop_model_.addElement(name);
        }
      } else if (state_ == InfoState.kSprite) {
        // sprite shop in model
        ArrayList<String> names = info_.getAllSpritesNames();
        for (String name : names) {
          shop_model_.addElement(name);
        }
      } else if (state_ == InfoState.kTeleport) {
        // teleport list in model
        ArrayList<String> names = info_.getPossibleTeleportDestinations();
        for (String name : names) {
          shop_model_.addElement(name);
        }
      } else if (state_ == InfoState.kInventory) {
        // inventory list in model
        ArrayList<String> names = info_.getAllInventoryItemsNames();
        for (String name : names) {
          shop_model_.addElement(name);
        }
      }
    }

    // show name
    if (shop_.getSelectedIndex() != -1) {
      String idv = (String)shop_.getSelectedValue();
      int idx = shop_.getSelectedIndex();
      switch (state_) {

        case kShop:
          shop_header_.setIcon(
                  new ImageIcon(
                  info_.getAllShopItemsImages().get(idx)));

          shop_helper_.setText("<html><table>"
                  + "<td width = '180'>Price: " +
                  info_.getAllShopItemsBuyPrices().get(idx) +
                  "<br/>Description:<br/>" +
                  info_.getAllShopItemsDescriptions().get(idx) +
                  "</td></table></html>");
          break;
        case kSprite:

          String status;
          if (info_.getAllSpritesIsHired().get(idx)) {
            status = "Hired";
          } else {
            status = "Not Hired";
          }
          shop_header_.setIcon(new ImageIcon(
                  info_.getAllSpritesImage().get(idx)));
          shop_helper_.setText("<html><table><td width = '180'>" +
                  status +
                  "<br/>" +
                  "Hire Price: " +
                  info_.getAllSpritesHirePrices().get(idx) +
                  "<br/>Description:<br/>" +
                  info_.getAllSpritesDescriptions().get(idx) +
                  "</td></table></html>");
          break;
        case kTeleport:
          shop_header_.setIcon(null);

          shop_helper_.setText("<html><table><td width = '180'>" +
                  "Description:<br/>" +
                  info_.getMapDescription((String)shop_.getSelectedValue()) +
                  "</td></table></html>");
          break;
        case kInventory:
          shop_header_.setIcon(
                  new ImageIcon(
                  info_.getAllInventoryItemsImages().get(idx)));
          shop_helper_.setText(
                  "<html><table><td width='180'>" +
                  "Quantity: " +
                  info_.getAllInventorySlotsNumberOfItems().get(idx) +
                  "<br/>Sell Price: " +
                  info_.getAllInventorySellPrices().get(idx) +
                  "</td></table><br/>Description<br/>" +
                  info_.getAllInventoryItemsDescriptions().get(idx));
          break;
      }
      //shop_header_.updateUI();
      //shop_helper_.updateUI();
    } else {
      shop_header_.setIcon(null);
      shop_helper_.setText("");
    }

    //shop_.updateUI();

    // update season
    season_.setIcon(new ImageIcon(info_.getCurrentSeasonImage()));
    //season_.updateUI();

    // update disaster
    disaster_.removeAll();
    ArrayList<Image> dimages = info_.getCurrentDisastersImage();
    int counter = 0;
    for (Image img : dimages) {
      JLabel taint = new JLabel(new ImageIcon(img));
      taint.setBounds(counter * 64, 0, 64, 64);
      ++counter;
      disaster_.add(taint);
    }
    disaster_.updateUI();

    // update time
    if (info_.isNight()) {
      time_.setText("Night of day " + info_.getCurrentDay() +
              " is starting.");
    } else {
      time_.setText("<html>Time:" + info_.getCurrentTime() + 
              "/" + info_.getDayLength() + "<br/>" +
              "day:" + info_.getCurrentDay() + "<br/>" +
              "money: " + info_.getMoney() + "</html>");
    }
    //time_.updateUI();

    // update item shown
    item_.setIcon(new ImageIcon(info_.getCurrentInventoryImage()));
    //item_.updateUI();

    // update tool shown
    tool_.setIcon(new ImageIcon(info_.getCurrentToolImage()));
    //tool_.updateUI();
    if (night_) return;
    if (info_.isNight()) {
      // solve night
      setEnabledAllButtons(false);
      // night starts
      night_ = true;
      night_timer_.cancel();
      night_timer_.purge();
      night_timer_ = new Timer();
      night_timer_.scheduleAtFixedRate(new NightTask(), kDelayInMs, kDelayInMs);
    }

  }

  /*public static void main(String [] args) {
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            GameEngine engine = new GameEngine();
            MainView app = new MainView(new GameController(engine),
                    new InformationLayer(engine));
            
          }
		});
	}*/

}
